package com.atguigu.gmall.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPObject;
import com.atguigu.gmall.common.cache.GmallCache;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.*;
import com.atguigu.gmall.product.service.MangerService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service

public class MangerServiceImpl implements MangerService {

    @Autowired
    BaseCategory1Mapper baseCategory1Mapper;

    @Autowired
    BaseCategory2Mapper baseCategory2Mapper;

    @Autowired
    BaseCategory3Mapper baseCategory3Mapper;

    @Autowired
    BaseAttrInfoMapper baseAttrInfoMapper;

    @Autowired
    BaseAttrValueMapper baseAttrValueMapper;

    @Autowired
    SpuInfoMapper spuInfoMapper;

    @Autowired
    BaseSaleAttrMapper baseSaleAttrMapper;

    @Autowired
    SpuSaleAttrMapper spuSaleAttrMapper;

    @Autowired
    SpuImageMapper spuImageMapper;

    @Autowired
    SpuPosterMapper spuPosterMapper;

    @Autowired
    SpuSaleAttrValueMapper spuSaleAttrValueMapper;

    @Autowired
    SkuInfoMapper skuInfoMapper;

    @Autowired
    SkuImageMapper skuImageMapper;

    @Autowired
    SkuSaleAttrValueMapper skuSaleAttrValueMapper;

    @Autowired
    SkuAttrValueMapper skuAttrValueMapper;

    @Autowired
    BaseCategoryViewMapper  baseCategoryViewMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    private BaseTrademarkMapper baseTrademarkMapper;

    @Autowired
    RabbitService rabbitService;

    @Override
    public List<BaseCategory1> getCategory1() {
        return baseCategory1Mapper.selectList(null);

    }

    @Override
    public List<BaseCategory2> CategoryId(Long categoryId) {
        QueryWrapper<BaseCategory2> wrapper = new QueryWrapper<>();
        wrapper.eq("category1_id", categoryId);
        List<BaseCategory2> baseCategory2List = baseCategory2Mapper.selectList(wrapper);
        return baseCategory2List;
    }

    @Override
    public List<BaseCategory3> getCategoryId3(Long categoryId2) {
        QueryWrapper<BaseCategory3> wrapper = new QueryWrapper<>();
        wrapper.eq("category2_id", categoryId2);
        List<BaseCategory3> baseCategory3List = baseCategory3Mapper.selectList(wrapper);
        return baseCategory3List;
    }

    @Override
    public List<BaseAttrInfo> attrInfoList(Long categoryId, Long categoryId2, Long categoryId3) {
        return baseAttrInfoMapper.selectBaseAttrInfo(categoryId, categoryId2, categoryId3);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAttrInfo(BaseAttrInfo baseAttrInfo) {
        baseAttrInfoMapper.insert(baseAttrInfo);
        //获取平台的所有属性值，然后遍历
        List<BaseAttrValue> attrValueList = baseAttrInfo.getAttrValueList();
        if (!CollectionUtils.isEmpty(attrValueList)) {
            attrValueList.stream().forEach((baseAttrValue) -> {
                baseAttrValueMapper.insert(baseAttrValue);
            });
        }
    }

    @Override
    public List<BaseAttrValue> getAttrValueList(Long attrId) {
        QueryWrapper<BaseAttrValue> wrapper = new QueryWrapper<>();
        wrapper.eq("attr_id", attrId);
        return baseAttrValueMapper.selectList(wrapper);
    }

    @Override
    public BaseAttrInfo getBaseAttrInfo(Long attrId) {
        BaseAttrInfo baseAttrInfo = baseAttrInfoMapper.selectById(attrId);
        if (baseAttrInfo != null) {
            baseAttrInfo.setAttrValueList(getAttrValueList(attrId));
        }
        return baseAttrInfo;
    }

    @Override
    public IPage<SpuInfo> getSpuInfoList(Page pageModel, SpuInfo spuInfo) {
        QueryWrapper<SpuInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("category3_id", spuInfo.getCategory3Id());
        wrapper.orderByDesc("id");
        return spuInfoMapper.selectPage(pageModel, wrapper);
    }

    @Override
    public List<BaseSaleAttr> baseSaleAttrList() {

        return baseSaleAttrMapper.selectList(null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSpuInfo(SpuInfo spuInfo) {

        spuInfoMapper.insert(spuInfo);
        List<SpuImage> spuImageList = spuInfo.getSpuImageList();
        if (!CollectionUtils.isEmpty(spuImageList)) {
            spuImageList.stream().forEach(spuImage -> {
                spuImage.setSpuId(spuInfo.getId());
                spuImageMapper.insert(spuImage);
            });
        }

        List<SpuPoster> spuPosterList = spuInfo.getSpuPosterList();
        if (!CollectionUtils.isEmpty(spuPosterList)) {
            spuPosterList.stream().forEach(spuPoster -> {
                spuPoster.setSpuId(spuInfo.getId());
                spuPosterMapper.insert(spuPoster);
            });
        }
        List<SpuSaleAttr> spuSaleAttrList = spuInfo.getSpuSaleAttrList();
        if (!CollectionUtils.isEmpty(spuSaleAttrList)) {
            spuSaleAttrList.stream().forEach(spuSaleAttr -> {
                spuSaleAttr.setSpuId(spuInfo.getId());
                spuSaleAttrMapper.insert(spuSaleAttr);

                List<SpuSaleAttrValue> spuSaleAttrValueList = spuSaleAttr.getSpuSaleAttrValueList();
                if (!CollectionUtils.isEmpty(spuSaleAttrValueList)) {
                    spuSaleAttrValueList.stream().forEach(spuSaleAttrValue -> {
                        //获取销售属性名称
                        spuSaleAttrValue.setSaleAttrName(spuSaleAttr.getSaleAttrName());
                        spuSaleAttrValue.setSpuId(spuInfo.getId());
                        spuSaleAttrValueMapper.insert(spuSaleAttrValue);
                    });
                }
            });
        }
    }

    @Override
    public SpuInfo getSpuInfo(Long spuId) {

        SpuInfo spuInfo = spuInfoMapper.selectById(spuId);

        QueryWrapper<SpuSaleAttr> wrapper = new QueryWrapper<>();
        wrapper.eq("spu_id", spuId);
        List<SpuSaleAttr> spuSaleAttrList = spuSaleAttrMapper.selectList(wrapper);
        spuInfo.setSpuSaleAttrList(spuSaleAttrList);

        spuSaleAttrList.stream().forEach(spuSaleAttr -> {
            QueryWrapper<SpuSaleAttrValue> saleAttrValueQueryWrapper = new QueryWrapper<>();
            saleAttrValueQueryWrapper.eq("spu_id", spuId);
            saleAttrValueQueryWrapper.eq("base_sale_attr_id", spuSaleAttr.getBaseSaleAttrId());
            List<SpuSaleAttrValue> spuSaleAttrValues = spuSaleAttrValueMapper.selectList(saleAttrValueQueryWrapper);
            spuSaleAttr.setSpuSaleAttrValueList(spuSaleAttrValues);
        });
        spuInfo.setSpuSaleAttrList(spuSaleAttrList);

        QueryWrapper<SpuPoster> posterQueryWrapper = new QueryWrapper<>();
        posterQueryWrapper.eq("spu_id", spuId);
        List<SpuPoster> spuPosterList = spuPosterMapper.selectList(posterQueryWrapper);
        spuInfo.setSpuPosterList(spuPosterList);

        QueryWrapper<SpuImage> ImageQueryWrapper = new QueryWrapper<>();
        ImageQueryWrapper.eq("spu_id", spuId);
        List<SpuImage> spuImageList = spuImageMapper.selectList(ImageQueryWrapper);
        spuInfo.setSpuImageList(spuImageList);
        return spuInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSpuInfo(SpuInfo spuInfo) {

        spuInfoMapper.updateById(spuInfo);


        QueryWrapper<SpuImage> imageQueryWrapper = new QueryWrapper<>();
        imageQueryWrapper.eq("spu_id", spuInfo.getId());
        spuImageMapper.delete(imageQueryWrapper);
        List<SpuImage> spuImageList = spuInfo.getSpuImageList();
        if (!CollectionUtils.isEmpty(spuImageList)) {
            spuImageList.stream().forEach(spuImage -> {
                spuImage.setSpuId(spuInfo.getId());
                spuImageMapper.insert(spuImage);
            });
        }

        QueryWrapper<SpuPoster> posterQueryWrapper = new QueryWrapper<>();
        imageQueryWrapper.eq("spu_id", spuInfo.getId());
        spuPosterMapper.delete(posterQueryWrapper);
        List<SpuPoster> spuPosterList = spuInfo.getSpuPosterList();
        if (!CollectionUtils.isEmpty(spuPosterList)) {
            spuPosterList.stream().forEach(spuPoster -> {
                spuPoster.setSpuId(spuInfo.getId());
                spuPosterMapper.insert(spuPoster);
            });
        }

        QueryWrapper<SpuSaleAttr> saleAttrQueryWrapper = new QueryWrapper<>();
        imageQueryWrapper.eq("spu_id", spuInfo.getId());
        spuSaleAttrMapper.delete(saleAttrQueryWrapper);

        QueryWrapper<SpuSaleAttrValue> saleAttrValueQueryWrapper = new QueryWrapper<>();
        imageQueryWrapper.eq("spu_id", spuInfo.getId());
        spuSaleAttrValueMapper.delete(saleAttrValueQueryWrapper);

        List<SpuSaleAttr> spuSaleAttrList = spuInfo.getSpuSaleAttrList();
        if (!CollectionUtils.isEmpty(spuSaleAttrList)) {
            spuSaleAttrList.stream().forEach(spuSaleAttr -> {
                spuSaleAttr.setSpuId(spuInfo.getId());
                spuSaleAttrMapper.insert(spuSaleAttr);

                List<SpuSaleAttrValue> spuSaleAttrValueList = spuSaleAttr.getSpuSaleAttrValueList();
                if (!CollectionUtils.isEmpty(spuSaleAttrValueList)) {
                    spuSaleAttrValueList.stream().forEach(spuSaleAttrValue -> {
                        //获取销售属性名称
                        spuSaleAttrValue.setSaleAttrName(spuSaleAttr.getSaleAttrName());
                        spuSaleAttrValue.setSpuId(spuInfo.getId());
                        spuSaleAttrValueMapper.insert(spuSaleAttrValue);
                    });
                }
            });
        }
    }

    @Override
    public List<SpuImage> spuImageList(Long spuId) {
        return spuImageMapper.selectList(new QueryWrapper<SpuImage>().eq("spu_id",spuId));
    }

    @Override
    public List<SpuSaleAttr> spuSaleAttrList(Long spuId) {

        return spuSaleAttrMapper.selectSpuSaleAttrList(spuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSkuInfo(SkuInfo skuInfo) {

        //skuinfo skuImage skuSaleAttrValue SkuAttrValue
        skuInfoMapper.insert(skuInfo);

        //skuImage
        List<SkuImage> skuImageList = skuInfo.getSkuImageList();
        if(!CollectionUtils.isEmpty(skuImageList)){
            skuImageList.stream().forEach(skuImage -> {
                skuImage.setSkuId(skuInfo.getId());
                skuImageMapper.insert(skuImage);
            });
        }
        List<SkuAttrValue> skuAttrValueList = skuInfo.getSkuAttrValueList();
        if(!CollectionUtils.isEmpty(skuAttrValueList)){
            skuAttrValueList.stream().forEach(skuAttrValue -> {
                skuAttrValue.setSkuId(skuInfo.getId());
                skuAttrValueMapper.insert(skuAttrValue);
            });
        }
        List<SkuSaleAttrValue> skuSaleAttrValueList = skuInfo.getSkuSaleAttrValueList();
        if(!CollectionUtils.isEmpty(skuSaleAttrValueList)){
            skuSaleAttrValueList.stream().forEach(skuSaleAttrValue -> {
                skuSaleAttrValue.setSkuId(skuInfo.getId());
                skuSaleAttrValue.setSpuId(skuInfo.getSpuId());
                skuSaleAttrValueMapper.insert(skuSaleAttrValue);
            });
        }
        //添加到布隆过滤器中
        RBloomFilter<Object> bloomFilter = this.redissonClient.getBloomFilter(RedisConst.SKU_BLOOM_FILTER);
        bloomFilter.add(skuInfo.getId());
    }

    @Override
    public IPage<SkuInfo> SkuInfolist(Page<SkuInfo> skuInfoIPage, SkuInfo skuInfo) {

        QueryWrapper<SkuInfo> skuInfoQueryWrapper = new QueryWrapper<>();
        skuInfoQueryWrapper.eq("category3_id",skuInfo.getCategory3Id());
        skuInfoQueryWrapper.orderByDesc("id");
        Page<SkuInfo> InfoPage = skuInfoMapper.selectPage(skuInfoIPage, skuInfoQueryWrapper);
        return InfoPage;
    }

    @Override
    public void onSale(Long skuId) {
        SkuInfo skuInfo = new SkuInfo();
        skuInfo.setId(skuId);
        skuInfo.setIsSale(1);
        this.skuInfoMapper.updateById(skuInfo);

        //商品上架
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_GOODS,MqConst.ROUTING_GOODS_UPPER,skuId);
    }

    @Override
    public void cancelSale(Long skuId) {
        SkuInfo skuInfo = new SkuInfo();
        skuInfo.setId(skuId);
        skuInfo.setIsSale(0);
        this.skuInfoMapper.updateById(skuInfo);

        //商品下架
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_GOODS,MqConst.ROUTING_GOODS_LOWER,skuId);
    }

    @GmallCache(prefix = RedisConst.SKUKEY_PREFIX)
    @Override
    public SkuInfo getSkuInfo(Long skuId) {

        //  this.redissonClient.getLock("");
        return getSkuInfoDB(skuId);
      //  return getSkuInfoByRedisson(skuId);
    }

    private SkuInfo getSkuInfoByRedisson(Long skuId) {
        SkuInfo skuInfo = null;

        try {
            String skuKey = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKUKEY_SUFFIX;

            skuInfo = (SkuInfo) this.redisTemplate.opsForValue().get(skuKey);

            if (skuInfo == null) {
                //说明缓存没有数据
                String lockKey = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKUKEY_SUFFIX;

                RLock lock = this.redissonClient.getLock(lockKey);

                boolean result = lock.tryLock(RedisConst.SKULOCK_EXPIRE_PX1, RedisConst.SKULOCK_EXPIRE_PX2, TimeUnit.SECONDS);

                //判断
                if (result) {
                    try {
                        skuInfo = this.getSkuInfoDB(skuId);
                        //判断
                        if (skuInfo == null) {
                            SkuInfo skuInfo1 = new SkuInfo();
                            this.redisTemplate.opsForValue().set(skuKey, skuInfo1, RedisConst.SKUKEY_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
                            //返回数据
                            return skuInfo1;
                        }
                        this.redisTemplate.opsForValue().set(skuKey, skuInfo, RedisConst.SKUKEY_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
                        return skuInfo;
                    } finally {
                        //解锁
                        lock.unlock();
                    }
                }
            } else {
                //说明缓存有数据
                return skuInfo;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
        }

        return getSkuInfoDB(skuId);
    }

    /**
     * 表示从数据库中获取数据
     * @param skuId
     * @return
     */
    private SkuInfo getSkuInfoDB(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);

        QueryWrapper<SkuImage> wrapper = new QueryWrapper<>();
        wrapper.eq("sku_id", skuId);
        List<SkuImage> skuImageList = skuImageMapper.selectList(wrapper);
        skuInfo.setSkuImageList(skuImageList);
        return skuInfo;
    }

    @GmallCache(prefix = "getCategoryViewBycategory3Id:")
    @Override
    public BaseCategoryView getCategoryViewBycategory3Id(Long category3Id) {

        return baseCategoryViewMapper.selectById(category3Id);
    }


    @Override
    public BigDecimal getSkuPrice(Long skuId) {

        //select price from sku_Info where id = skuId
        QueryWrapper<SkuInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("id",skuId);
        wrapper.select("price");
        SkuInfo skuInfo = skuInfoMapper.selectOne(wrapper);
        if(skuInfo != null){
            return skuInfo.getPrice();
        }
        return new BigDecimal(0);
    }

    @GmallCache(prefix = "getSpuSaleAttrListCheckBySku:")
    @Override
    public List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(Long skuId, Long spuId) {

        return spuSaleAttrMapper.selectSpuSaleAttrListCheckBySku(skuId,spuId);

    }

    @GmallCache(prefix = "getSkuValueIdsMap:")
    @Override
    public Map getSkuValueIdsMap(Long spuId) {
        HashMap<Object,Object> hashMap = new HashMap<>();

        List<Map> mapList = this.skuSaleAttrValueMapper.sclectSkuValueIdsMap(spuId);
        if(!CollectionUtils.isEmpty(mapList)){
            for(Map map : mapList){
                hashMap.put(map.get("value_ids"),map.get("sku_id"));
            }
        }
        return hashMap;
    }

    @GmallCache(prefix = "findSpuPosterBySpuId:")
    @Override
    public List<SpuPoster> findSpuPosterBySpuId(Long spuId) {
        return spuPosterMapper.selectList(new QueryWrapper<SpuPoster>().eq("spu_id",spuId));
    }

    @GmallCache(prefix = "getAttrList:")
    @Override
    public List<BaseAttrInfo> getAttrList(Long skuId) {
        return baseAttrInfoMapper.selectAttrList(skuId);
    }

    @Override
    @GmallCache(prefix = "getBaseCategoryList:")
    public List<JSONObject> getBaseCategoryList() {
        //创建一个集合
        List<JSONObject> list = new ArrayList<>();

        List<BaseCategoryView> baseCategoryViewList = baseCategoryViewMapper.selectList(null);
        Map<Long, List<BaseCategoryView>> category1Map = baseCategoryViewList.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory1Id));
        int index = 1;
        for ( Map.Entry<Long, List<BaseCategoryView>> entry1 : category1Map.entrySet()) {
            //获取分级Id
            Long category1Id = entry1.getKey();
            //获取一级分类之下的所有集合
            List<BaseCategoryView> category2IdList = entry1.getValue();
            JSONObject category1 = new JSONObject();
            category1.put("index",index);
            category1.put("categoryId",category1Id);

            category1.put("categoryName",category2IdList.get(0).getCategory1Name());
            index++;

            Map<Long, List<BaseCategoryView>> category2Map = category2IdList.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));
            List<JSONObject> category2Child = new ArrayList<>();
            for (Map.Entry<Long, List<BaseCategoryView>> entry2 : category2Map.entrySet()) {
                Long category2Id = entry2.getKey();
                List<BaseCategoryView> category3IdList = entry2.getValue();

                JSONObject category2 = new JSONObject();
                category2.put("categoryId",category2Id);
                category2.put("categoryName",category3IdList.get(0).getCategory2Name());
                //添加到二级分类集合中
                category2Child.add(category2);

                ArrayList<Object> category3Child = new ArrayList<>();
                //循环三级Id
                category3IdList.forEach(baseCategoryView -> {
                    JSONObject category3 = new JSONObject();
                    category3.put("categoryId",baseCategoryView.getCategory3Id());
                    category3.put("categoryName",baseCategoryView.getCategory3Name());
                    category3Child.add(category3);
                });
                //将三级数据放到二级中
                category2.put("categoryChild",category3Child);
            }
            //将二级数据放到一级中
            category1.put("categoryChild",category2Child);
            list.add(category1);
        }
        return list;
    }

    @Override
    public BaseTrademark getTrademark(Long tmId) {
        return baseTrademarkMapper.selectById(tmId);
    }


}